UI XML tutorial
World of Warcraft has a fairly powerful layout engine for creating user interfaces. When combined with lua for attaching behaviours to UI elements, this creates a flexible system with which the game's entire UI is created, as well as any custom AddOns. This page started as a braindump of various aspects of the XML engine and API; over time, it has become a more useful reference, though it is still far from complete. For more information on creating AddOns, see AddOns, Interface Customization, World of Warcraft API and especially the Widget API which describes the programming aspects of all XML objects. Note that this assumes familiarity with XML; for a quick introduction, see this XML Introduction at xmlfiles.com. Also note that the xml declaration () seems to choke up the Blizzard xml parser and should be omitted from UI .xml files. Also note that as of version 1.10, all types of frames can also be created from LUA with the new CreateFrame() API. = The Basics = An XML file is a collection of elements (with a start and end tag), of which the User Interface files are no exception. There are two main types of elements that appear in the UI XML files. The first type are those that declare user interface items (or widgets), such as Buttons, Frames, Checkboxes. We will call these widget elements. The second type of elements, which always occur inside the first type, define properties and behaviour of the widgets. We will call these property elements. Here is an example: The Button element is of the first type, in other words a widget element. Its appearance in the XML file causes a Button with the name MyButton to be created. The elements inside it (such as Anchors, Anchor) define its properties, hence are of the second type. The general structure is always the same, you have elements representing widgets, and other elements inside them representing their properties. It can also happen that a widget element is inside another one. For example: This example has two widget elements (Frame and Button), and several property elements (Anchors, Anchor). This creates a Frame, with a Button inside it. Here, MyButton is a child of MyFrame, and MyFrame is a parent of MyButton. Also note how the XML convention of abbreviating an empty element such as as is used. Many of the elements (widget and property alike) can have attributes, such as the name attribute in the above examples. A complete and valid XML file must contain exactly one element named UI, with some rather long attributes (best use copy/paste for this). Hence a minimal example of a complete UI XML file would be something like: Such a file will create a single Frame, named MyFrame. However, that Frame wouldn't be visible and wouldn't have any content. = Validation with XSD = If you use the Blizzard Interface Customization tool to extract the contents of the Interface\FrameXML folder, you will come across the file UI.xsd which provides a schema definition for automated validation of your customized XML-files. Notice that XSD is an advanced XML feature and requires a special editor as well as a good knowledge of advanced XML-concepts. If you've already worked with XML you might find this very helpful to get started with WoW. = Naming Widgets = Every widget element may have the name attribute. If an element has a name, it causes a global Lua variable to be created with that name. This variable can then be used to call API methods on that widget. (See Widget API for a list of methods available for the different UI widgets.) Note that global variables are truly global across the entire UI, meaning that every name must be unique across all XML files. Here is an example. Let's say in your XML file you have a section like this: .. .. In any Lua code then you can use the variable MyAddon_Frame to refer to the frame and MyAddon_Button to refer to the button. For example, to show the frame, call MyAddon_Frame:Show(). Or to disable the button, call MyAddon_Button:Disable(). When defining the name of a widget, the special string $parent may be used. This will take on the name of whatever the parent of that widget is. For example: .. .. This results in two global Lua variables: MyAddon_Frame and MyAddon_Frame_Button. = Managing Frames = Note: A lot of this section applies to all user interface widgets, not just Frames. Properties for layout, sizing and so on are common to all widgets. Layout Frames have a combination of a size and one or more anchors. For a frame to be laid out, the combination of these needs to define a rectangle on the screen in which the frame is to be laid out. A size is specified using a Size element with either an AbsDimension or RelDimension child element. Anchors allow for relative positioning, and also to allow frames to dynamically reposition their content based on resizing. A group of anchors is expressed via an Anchors element with one or more Anchor children, each of which may have an Offset. Some examples: TODO: Get screenshots of all of these This specifies a 100x100 frame anchored so that its top left is at the top left of its parent frame. This specifies a frame that covers half of your UI (regardless to the selected resolution). This specifies a 100x100 frame anchored so that its top left is at the top right of its parent frame. This specifies a 100x100 frame anchored at the top left of the frame SomeOtherFrame, and offset by 10 pixels to the right and 10 pixels down. (Note that the Y axis increases from the bottom up, so negative Y coordinates indicate downwards movement). Note that no Size is specified here; the size and location of this frame is defined entirely by its relationship to SomeOtherFrame. In particular, it will be inset by 5 pixels from the top left and bottom right of SomeOtherFrame. As SomeOtherFrame changes size, our frame will change size as well. Showing/Hiding Frames may be shown or hidden by FrameName:Hide() and FrameName:Show(). Also available are ShowUIPanel(FrameName) and HideUIPanel(FrameName). Layers and Textures There are 3 levels of layers: BACKGROUND is in the back, ARTWORK is in the middle and OVERLAY is in front. If you want to be sure that a object is before another, you must specify the level where you want to place it. BACKGROUND - Level 0. Place the background of your frame here. BORDER - Level 1. Place the artwork of your frame here . ARTWORK - Level 2. Place the artwork of your frame here. OVERLAY - Level 3. Place your text, objects, and buttons in this level HIGHLIGHT - Level 4. Place your text, objects, and buttons in this level Note: The above are capitalized for a reason. See example: ... ... ... Using Templates = Scripts = To attach behaviour to the UI elements defined in the XML files, you must use Lua. There are two methods of attaching Lua code to UI elements. * Short codes can go directly in the XML files in the appropriate event handler element (see later). * Long codes should go in a separate .lua file, and included via a Script element. To include Lua code via a Script element, you must have one or more